﻿using System;
using System.Text;
using System.Xml;
using System.Configuration;
using Microsoft.SharePoint;
using System.Runtime.InteropServices;

namespace Version3.SharePoint
{
    //This is list event handler that clears the read marks
    //if any of the field data other than the read marks is
    //updated. It is registered by the column configuration
    //processing.
    [Guid("483CE848-894A-4bd5-A10B-089A311DF622")]
    [CLSCompliant(false)]
    public class ReadUnreadListItemEventHandler : SPItemEventReceiver
    {
        #region ItemAdded

        public override void ItemAdded(SPItemEventProperties properties)
        {
            //DebugPause("ItemAdded");
            //this item only fires if an item is added and the field is
            //configured to clear read marks. Since we also want to
            //clear parent folder marks when an item is added, we will
            //forward this even to the ItemUpdated event for processing
            this.ItemUpdated(properties);
        }
        #endregion
 
       
        #region ItemUpdated
        public override void ItemUpdated(SPItemEventProperties properties)
        {
            //DebugPause("ItemUpdated");

            //if we have any fields that should have their read marks reset
            //we will do it here. Itterate over the fields, and insepct them if 
            //are of our type with ReadMark clearing configured
            //will be reset so that only the author has read it

            this.DisableEventFiring();
            bool fieldFound = ClearItemReadMarks(properties.CurrentUserId, properties.ListItem);
            if (fieldFound)
            {
                if(UtilityMethods.ListSupportsFolders(properties.ListItem.ParentList))
                {
                    ClearParentFolderReadMarks(properties.CurrentUserId, properties.ListItem);
                }
            }
            this.EnableEventFiring();
        }
        #endregion

        #region Utilities
        private bool ClearItemReadMarks(int exceptThisUserId, SPListItem listItem)
        {
            bool returnValue = false;

            foreach (SPField readUnreadField in listItem.Fields)
            {
                if (typeof(ReadUnreadMarksDataField).Name == readUnreadField.TypeAsString)
                {
                    ReadUnreadMarksDataField castField = (ReadUnreadMarksDataField)readUnreadField;
                    if (castField.ClearReadMarksOnUpdate)
                    {
                        ReadUnreadMarksDataFieldValue newValue = new ReadUnreadMarksDataFieldValue();
                        newValue.MarkUserRead(exceptThisUserId);
                        listItem[readUnreadField.InternalName] = newValue;
                        returnValue = true;
                    }
                }
            }
            //Its assumed that event fireing is disabled so call the normal SystemUpdate();
            //Since we are already in an update process it would be silly to use the 
            //direct column manipulation routines, 
            if (returnValue)
            {
                listItem.SystemUpdate();
            }
            return returnValue;
        }

        private void ClearParentFolderReadMarks(int exceptThisUserId, SPListItem listItem)
        {
            //we get here if the list supports foldering
            //and at least one of the columns is configured
            //for clearing read marks on update
            SPFolder parentFolder = UtilityMethods.ParentFolder(listItem);
            if (null != parentFolder)
            {
                //walk up the hierarchy clearing all the folder readmarks
                //all the way to the top of the tree
                bool fieldFound = ClearItemReadMarks(exceptThisUserId, parentFolder.Item);
                if (fieldFound)
                {
                    ClearParentFolderReadMarks(exceptThisUserId, parentFolder.Item);
                }
            }
        }

       
        internal static void DebugPause(string eventName)
        {
            string debugMessage = "Connect to process #";
            debugMessage += System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
            System.Windows.Forms.MessageBox.Show(debugMessage, "DEBUG-" + eventName,
                                                 System.Windows.Forms.MessageBoxButtons.OK,
                                                 System.Windows.Forms.MessageBoxIcon.Exclamation,
                                                 System.Windows.Forms.MessageBoxDefaultButton.Button1,
                                                 System.Windows.Forms.MessageBoxOptions.ServiceNotification);
        }
        #endregion
    }
}
